#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define N 6

// void runChild()
// {
//     //子进进程执行主逻辑
//     int cnt = 5;
//     while(cnt)
//     {
//         printf("I am father, pid : %d, ppid : %d, cnt : %d\n",getpid(), getppid(), cnt);
//         cnt--;
//         sleep(1);
//     }
// }

#define TASK_NUM 10

typedef void(*task_t)();
task_t TASKS[TASK_NUM];

void task1()
{
    printf("这是一个执行保存日志信息任务\n");
}

void task2()
{
    printf("这是一个执行调连接云服务器任务\n");
}

void task3()
{
    printf("这是一个执行查看内存剩余容量任务\n");
}

int AddTask(task_t t);

//初始化
void InitTasks()
{
    for(int i = 0; i < TASK_NUM; i++)
    {
        TASKS[i] = NULL;
    }
    AddTask(task1);
    AddTask(task2);
    AddTask(task3);
}

int AddTask(task_t t)
{
    int pos = 0;
    for(; pos < TASK_NUM; pos++)
    {
        if(!TASKS[pos]) break;
    }
    if(pos == TASK_NUM) 
        return -1;

    TASKS[pos] = t;
    return 0; 
}

void ExecuteTask()
{
    for(int i = 0; i < TASK_NUM; i++)
    {
        if(!TASKS[i]) continue;

        TASKS[i]();
    }
}

int main()
{
    // //创建批量进程
    // for(int i = 0; i < 6; i++)
    // {
    //     pid_t id = fork();
    //     if(id == 0)
    //     {
    //         runChild();
    //         exit(i);
    //     }
    //     printf("create child process: %d success\n", id); // 这句话只有父进程才会执行
    // }
    
    // sleep(10);//有5s所有子进程僵尸。观察子进程状态变化
    // //等待多个子进程
    // for(int i = 0; i < N; ++i)
    // {
    //     int status = 0;
    //     //pid_t ret = wait(NULL);
    //     pid_t ret = waitpid(-1, &status, 0);
    //     if(ret > 0)
    //     {
    //         printf("process wait : %d success, exitcode : %d\n", ret,WEXITSTATUS(status));
    //     }
    // }
    // sleep(5);

    pid_t id = fork(); // 创建子进程
    if(id < 0) // 创建失败
    {
        perror("fork");
        return 1;
    }
    else if(id == 0) // 子进程
    {
        //int *p = NULL;
        int cnt = 5;
        while(cnt)
        {
            printf("I am child, pid : %d, ppid : %d, cnt : %d\n",getpid(), getppid(), cnt);
            sleep(1);
            --cnt;
            // *p = 10;
            // int a = 10;
            // int b = a / 0;
        }
        exit(1);
    }
    else // 父进程
    {
        // int cnt = 10;
        // while(cnt)
        // {
        //     printf("I am father, pid : %d, ppid : %d, cnt : %d\n",getpid(), getppid(), cnt);
        //     --cnt;
        //     sleep(1);
        // }

        //pid_t ret = wait(NULL);
        int status = 0;
        InitTasks();
        while (1) // 轮询
        {
            pid_t ret = waitpid(-1, &status, WNOHANG); // WNOHANG 非阻塞
            if(ret > 0)
            {
                // printf("wait success : pid : %d, status : %d\n", getpid(), status);
                // 0x7f -> 01111111
                //printf("wait success : pid : %d, exitcode : %d, signal : %d\n", getpid(), status >> 8 & 0xff, status & 0x7f);

                if(WIFEXITED(status)) //正常退出
                {
                    printf("进程正常退出，退出码： %d\n", WEXITSTATUS(status));
                    break;
                }
                else 
                {
                    printf("进程异常终止\n");
                    break;
                }
            }
            else if(ret < 0) // 等待失败返回-1
            {
                perror("wait");
                exit(-1);
                break;
            }
            else 
            {
                //printf("子进程还没结束，我再等等...\n");
                ExecuteTask();
                usleep(500000);
            }

//            sleep(5);
        } 
    }       
    return 0;
}